package com.me.libgdx_test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

import com.badlogic.gdx.math.Rectangle;

public class ClassPlaceObjects {
	private Random random = new Random(System.currentTimeMillis());
	private ArrayList<ClassCharacterEnemy> enemies;
	private ArrayList<ClassObjectPickupDungeon> pickups;
	private ArrayList<ClassObjectShopDungeon> shops;
	private ArrayList<ClassObjectTotem> totems;
	private ArrayList<ClassObjectSpellDungeon> spells;
	private ArrayList<ClassObjectGodDungeon> gods;
	private ArrayList<Point> placed_things,shroud;
	private int[][] dungeon;
	private ClassReferenceDrawable game_vars;
	private ClassLogDisplay logger;
	int pickup_frequency;
	int shop_frequency;
	int spell_frequency;
	int enemy_frequency;
	int altar_frequency;
	private float shop_discount;
	float altar_discount;
	boolean tutorial_messages;
	ClassCharacterPlayer player;
	ClassPermanentUpgrades perm_upgrades;
	ClassPlaceObjects(ClassReferenceDrawable game_vars, int[][] dungeon, ClassCharacterPlayer player, ClassPermanentUpgrades perm_upgrades){
		logger = new ClassLogDisplay("ClassPlaceObject");
		this.game_vars = game_vars;
		this.perm_upgrades = perm_upgrades;
		this.dungeon = dungeon;
		placed_things = new ArrayList<Point>();
		shroud = new ArrayList<Point>();
		placed_things.add(player.get_location());
		this.player = player;
		init_placed_things();
		
		pickup_frequency = 3;
		shop_frequency = 10;
		spell_frequency = 5+game_vars.player_level/5;
		enemy_frequency = (int)(40+(1+Math.floor(this.game_vars.player_level/10)));
		altar_frequency = 5;
		shop_discount = 0;
		altar_discount = 0;
		
		//This adjusts the frequency of each object if the player class requires it
		player.get_class_mods().playerPickupStructureMod.set_item_frequency_discount(this);
		
		logger.print("ShopDiscount: " + shop_discount);
		shop_discount += perm_upgrades.get_upgrade_value("Barter");
		
		shop_discount = 1 - shop_discount;
		
		altar_frequency += perm_upgrades.get_upgrade_value("Cities");
		shop_frequency += perm_upgrades.get_upgrade_value("Cities");
		altar_discount += perm_upgrades.get_upgrade_value("Religion");
		
		pickups = new ArrayList<ClassObjectPickupDungeon>();
		enemies = new ArrayList<ClassCharacterEnemy>();
		shops = new ArrayList<ClassObjectShopDungeon>();
		gods = new ArrayList<ClassObjectGodDungeon>();
		spells = new ArrayList<ClassObjectSpellDungeon>();
		totems = new ArrayList<ClassObjectTotem>();

		if(game_vars.player_level!=0){
			tutorial_messages = false;
			place_items();
		}else{
			tutorial_messages = true;
			place_tutorial();
		}
	}
	
	public void place_tutorial(){
		
		//% - 2 => Gold
		//x - 3 => Enemy
		//S - 4 => Shop
		//G - 5 => Glyph
		//A - 6 => Altar
		
		//This is a map of the objects
		int[][] mapTemplate = {
				{0,0,0,1,2,2,2,1,0,0,0,1,3,3,3,3,3,3,3,0}, //0
				{0,0,0,3,2,4,2,3,0,2,0,1,0,1,1,1,1,1,0,0}, //1
				{0,0,0,1,2,2,2,1,0,0,0,1,0,1,0,0,0,1,0,0}, //2
				{1,1,1,1,1,1,1,1,1,3,1,1,5,1,3,1,0,1,4,0}, //3
				{0,0,0,3,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0}, //4
				{0,2,0,3,0,0,5,0,3,5,0,1,3,0,0,0,3,1,0,0}, //5
				{0,0,0,3,0,0,0,0,1,0,2,1,1,1,1,1,1,1,3,1}, //6
				{1,3,1,1,1,1,1,1,1,1,1,1,4,0,0,6,0,0,0,0}, //7
				{0,5,1,0,0,0,0,3,1,0,0,0,0,0,0,0,0,0,0,0}, //8
				{0,0,1,0,2,0,1,0,1,3,1,1,1,1,1,1,1,1,1,1}, //9
				{0,1,1,0,2,0,1,0,1,0,0,2,0,3,0,2,0,0,0,0}, //10
				{0,0,3,0,0,0,1,0,1,0,0,2,0,3,0,2,0,0,0,0}, //11
				{1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,0,5,1,1,3}, //12
				{0,0,0,0,3,0,0,0,1,2,0,0,0,0,1,1,1,1,0,0}, //13
				{0,2,2,0,3,0,3,0,1,2,2,2,0,0,3,0,0,1,4,0}, //14
				{0,0,0,0,3,0,0,0,1,2,0,0,0,0,1,0,0,1,0,0}, //15
				{1,1,1,3,1,1,1,1,1,1,1,1,3,1,1,0,0,1,0,0}, //16
				{2,0,0,0,1,0,3,4,1,0,0,3,0,0,1,0,0,3,0,0}, //17
				{2,0,0,0,3,0,3,0,3,0,0,3,0,2,1,0,0,1,0,0}, //18
				{2,0,0,0,1,0,3,0,1,0,0,3,0,2,1,0,0,1,0,4}  //19
		};
		
		//This a map of the level/type of the objects
		int[][] enemyTemplate = {
				{0,0,0,1,5,5,5,1,0,0,0,1,8,8,8,8,8,8,8,0}, //0
				{0,0,0,1,5,0,5,2,0,0,0,1,0,1,1,1,1,1,0,0}, //1
				{0,0,0,1,5,5,5,1,0,0,0,1,0,1,0,0,0,1,0,0}, //0
				{1,1,1,1,1,1,1,1,1,2,1,1,9,1,10,1,0,1,0,0}, //3
				{0,0,0,2,0,0,0,0,1,0,0,1,0,1,1,1,0,1,0,0}, //0
				{0,3,0,2,0,0,6,0,2,14,0,1,9,0,0,0,9,1,0,0}, //0
				{0,0,0,2,0,0,0,0,1,0,1,1,1,1,1,1,1,1,7,1}, //0
				{1,3,1,1,1,1,1,1,1,1,1,1,0,0,0,9,0,0,0,0}, //7
				{0,18,1,0,0,0,0,3,1,0,0,0,0,0,0,0,0,0,0,0}, //8
				{0,0,1,0,3,0,1,0,1,7,1,1,1,1,1,1,1,1,1,1}, //9
				{0,1,1,0,3,0,1,0,1,0,0,1,0,7,0,0,0,0,0,0}, //10
				{0,0,3,0,0,0,1,0,1,0,0,3,0,7,0,0,0,0,0,0}, //11
				{1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,0,5,1,1,6}, //10
				{0,0,0,0,4,0,0,0,1,5,0,0,0,0,1,1,1,1,0,0}, //13
				{0,2,4,0,4,0,9,0,1,5,5,5,0,0,6,0,0,1,0,0}, //10
				{0,0,0,0,4,0,0,0,1,5,0,0,0,0,1,0,0,1,0,0}, //10
				{1,1,1,4,1,1,1,1,1,1,1,1,6,1,1,0,0,1,0,0}, //10
				{0,0,0,0,1,0,5,0,1,0,0,6,0,0,1,0,0,6,0,0}, //17
				{1,0,0,0,4,0,5,0,5,0,0,6,0,2,1,0,0,1,0,0}, //18
				{3,0,0,0,1,0,5,0,1,0,0,6,0,4,1,0,0,1,0,0}  //19
		};

		ClassCustomMaps tutorial_map = new ClassCustomMaps(this,player,mapTemplate,enemyTemplate);
	}
	
	public void place_items(){
		place_enemies(enemy_frequency);
		place_objects(pickup_frequency);
		place_shops(shop_frequency);
		place_spells(spell_frequency);
		place_altars(altar_frequency);
		place_totems(5);
	}
	
	public void init_placed_things(){
		for(int y = 0;y< this.dungeon[0].length;y++){
			for(int x = 0; x< this.dungeon.length;x++){
				if (this.dungeon[x][y] == 1){
					placed_things.add(new Point(x,y));
				}
				shroud.add(new Point(x,y));
			}
		}
	}
	public void place_enemies(int to_place){
		ClassCharacterEnemy enemy_to_place;
		int enemy;
		int[] selectable_enemies = game_vars.levelObjects[game_vars.player_level].monsters;
		
		while(to_place > 0){
			Point guess = get_guess();
			enemy = random.nextInt( 4 );
			enemy_to_place = new ClassCharacterEnemy(game_vars.enemyObjects[selectable_enemies[enemy]]);
			enemy_to_place.set_location(guess);
			enemy_to_place.set_level(enemies.size()-to_place,game_vars.levelObjects[game_vars.player_level].difficulty);
			enemy_to_place.set_modifiers(game_vars.modObjects);
			player.get_class_mods().playerEnemyMod.set_enemy(enemy_to_place);
			placed_things.add(guess);
			enemies.add(enemy_to_place);
			to_place--;
		}
	}
	
	public void place_shops(int number_shops){
		ClassObjectShopDungeon object_holder;
		ArrayList<ClassDungeonShop> shop_items = new ArrayList<ClassDungeonShop>();
		ArrayList<ClassDungeonShop> upgradeable_used = new ArrayList<ClassDungeonShop>();
		
		while(number_shops > 0){
			Point guess = get_guess();
			while(shop_items.size()<3){
				ClassDungeonShop temp_holder = game_vars.shopObjects[random.nextInt(game_vars.shopObjects.length)];
				while(!temp_holder.actual_shop || (temp_holder.upgradeable && upgradeable_used.contains(temp_holder))){
					temp_holder = game_vars.shopObjects[random.nextInt(game_vars.shopObjects.length)];
				}
				if(temp_holder.upgradeable){upgradeable_used.add(temp_holder);}
				shop_items.add(new ClassDungeonShop(temp_holder));
			}
			object_holder = new ClassObjectShopDungeon(shop_items,
					this.game_vars.player_level+1,shop_discount);
			shop_items.clear();
			object_holder.set_location(guess);
			placed_things.add(guess);
			shops.add(object_holder);
			number_shops--;
		}
	}
	
	public void place_altars(int number_altars){
		ClassObjectGodDungeon object_holder;
		ClassDungeonGod holder;
		
		logger.print("Placing gods");
		while(number_altars > 0){
			Point guess = get_guess();
			holder = game_vars.godObjects[random.nextInt(game_vars.godObjects.length)];
			while(holder.altar_placed()){
				holder = game_vars.godObjects[random.nextInt(game_vars.godObjects.length)];
			}
			holder.placed_altar();
			logger.print(holder.Name);
			object_holder = new ClassObjectGodDungeon(holder,game_vars.get_god_map());
			object_holder.set_location(guess);
			placed_things.add(guess);
			gods.add(object_holder);
			number_altars--;
		}
	}
	
	public void place_objects(int number_pickups){
		logger.print(number_pickups);
		int count;
		ClassObjectPickupDungeon object_holder;
		
		//Goes through each of the pickups and places them number_pickups times
		for (ClassDungeonPickup object:game_vars.iconObjects){
			logger.print("pickup_middle");
			//Piety, life, and blood pools shouldn't be on the map at the start
			if (object.get_item_type()<6){
				count = number_pickups;
				count += perm_upgrades.add_gold(object);
				while(count > 0){
					Point guess = get_guess();
					object_holder = new ClassObjectPickupDungeon(object);
					object_holder.set_location(guess);
					placed_things.add(guess);
					pickups.add(object_holder);
					count--;
				}
			}
		}
		logger.print("pickup finish");
	}
	public void place_spells(int spell_count){
		ArrayList<ClassDungeonSpell> useable_spells = new ArrayList<ClassDungeonSpell>();
		
		for (ClassDungeonSpell spell:game_vars.spellObjects){
			if(spell.unlocked){
				useable_spells.add(spell);
				logger.print(spell.Name);
			}
		}
		//for(int i=0;i<spell_count;i++){
		while(spell_count>0 && useable_spells.size()>1){
			Point guess = get_guess();
			logger.print("Size: " + useable_spells.size());
			int spell_index = random.nextInt(useable_spells.size()-1);
			ClassObjectSpellDungeon spell_holder = new ClassObjectSpellDungeon(useable_spells.get(spell_index));
			spell_holder.set_location(guess);
			placed_things.add(guess);
			spells.add(spell_holder);
			useable_spells.remove(spell_index);
			spell_count--;
		}
	}
	public Point get_guess(){
		Point guess = new Point(random.nextInt(dungeon.length), random.nextInt(dungeon[0].length));
		while(placed_things.contains(guess)){guess.move(random.nextInt(dungeon.length),random.nextInt(dungeon[0].length));}
		return guess;
	}
	public void place_totems(int totem_count){
		totems = new ArrayList<ClassObjectTotem>();
	}
	//You can select these things, but you can't get through them
	public int[][] return_placed_map(){
		final int[][] return_map = new int[dungeon.length][dungeon[0].length];
		for(ClassCharacterEnemy enemy: enemies){
			return_map[enemy.get_location().x][enemy.get_location().y] = 1;
		}
		return return_map;
	}
	//You can't select these things and you cant get through them
	public int[][] return_composite_map(){
		final int[][] return_map = new int[dungeon.length][dungeon[0].length];
		for(int y = 0;y< this.dungeon[0].length;y++){
			for(int x = 0; x< this.dungeon.length;x++){
				return_map[x][y] = this.dungeon[x][y];
			}
		}
		for (ClassObjectTotem totem: totems){
			return_map[totem.get_location().x][totem.get_location().y] = 1;
		}
		for(Point shroud_point:shroud){
			return_map[shroud_point.x][shroud_point.y] = 1;
		}
		return return_map;
	}
	//You can't select these things and you cant get through them
	public int[][] return_composite_replaced_map(){
		final int[][] return_map = new int[dungeon.length][dungeon[0].length];
		for(int y = 0;y< this.dungeon[0].length;y++){
			for(int x = 0; x< this.dungeon.length;x++){
				return_map[x][y] = this.dungeon[x][y];
			}
		}
		for(ClassCharacterEnemy enemy: enemies){
			return_map[enemy.get_location().x][enemy.get_location().y] = 1;
		}
		for (ClassObjectTotem totem: totems){
			return_map[totem.get_location().x][totem.get_location().y] = 1;
		}
		for(Point shroud_point:shroud){
			return_map[shroud_point.x][shroud_point.y] = 1;
		}
		return return_map;
	}
	public int[][] return_shroud_map(){
		final int[][] return_map = new int[dungeon.length][dungeon[0].length];
		for(Point shroud_point:shroud){
			return_map[shroud_point.x][shroud_point.y] = 1;
		}
		return return_map;
	}
	public int visible_enemies(){
		int count = 0;
		for(ClassCharacterEnemy enemy: enemies){
			if(!shroud.contains(enemy.get_location())){
				count++;
			}
		}
		return count;
	}
	public boolean in_dungeon(Point location){
		Rectangle bounds = new Rectangle(0,0,this.dungeon.length,this.dungeon[0].length);
		return bounds.contains(location.x, location.y);
	}
	public ArrayList<Point> nothing_there(){
		ArrayList<Point> nothing_array = new ArrayList<Point>();
		Point test = new Point();
		boolean found;
		for(int y = 0;y< this.dungeon[0].length;y++){
			for(int x = 0; x< this.dungeon.length;x++){
				found = false;
				test.move(x, y);
				if (this.dungeon[x][y] != 1){
					for (ClassCharacterEnemy enemy: enemies){
						if(enemy.location.equals(test)){
							found = true;
						}
					}
					for (ClassObjectPickupDungeon pickup: pickups){
						if(pickup.get_location().equals(test)){
							found = true;
						}
					}
					for (ClassObjectShopDungeon shop: shops){
						if(shop.get_location().equals(test)){
							found = true;
						}
					}
					for (ClassObjectTotem totem: totems){
						if(totem.get_location().equals(test)){
							found = true;
						}
					}
					for (ClassObjectSpellDungeon spell: spells){
						if(spell.get_location().equals(test)){
							found = true;
						}
					}
					for (ClassObjectGodDungeon god: gods){
						if(god.get_location().equals(test)){
							found = true;
						}
					}
				}else{
					found = true;
				}
				if(!found){
					nothing_array.add(new Point(test));
				}
			}
		}
		return nothing_array;
	}
	public Point get_dungeon_dimensions(){
		return new Point(dungeon[0].length,dungeon.length);
	}
	public int get_dungeon(Point position){
		return dungeon[position.x][position.y];
	}
	public void set_dungeon(Point position,int value){
		dungeon[position.x][position.y] = value;
	}
	public ArrayList<ClassCharacterEnemy> get_enemies(){
		return enemies;
	}
	public void remove_enemy(ClassCharacterEnemy enemy){
		enemies.remove(enemy);
	}
	public void add_enemy(ClassCharacterEnemy enemy){
		enemies.add(enemy);
	}
	public ArrayList<ClassObjectShopDungeon> get_shops(){
		return shops;
	}
	public void remove_shop(ClassObjectShopDungeon shop){
		shops.remove(shop);
	}
	
	public ArrayList<Point> get_shroud(){
		return shroud;
	}
	public ClassObjectGodDungeon worshipping_god(){
		for(ClassObjectGodDungeon god:gods){
			if (god.worshipping){
				return god;
			}
		}
		return null;
	}
	public ArrayList<ClassObjectGodDungeon> get_gods(){
		return gods;
	}
	public ArrayList<Point> get_placed_things(){
		return placed_things;
	}
	public void remove_shroud(Point shroud_location){
		shroud.remove(shroud_location);
	}
    public ClassObjectTotem totem_there(Point location){
    	for (ClassObjectTotem totem: totems){
    		if(totem.get_location().equals(location)){return totem;}
    	}
    	return null;
    }
    public void remove_totem(ClassObjectTotem totem){
    	totems.remove(totem);
    }
    public ArrayList<ClassObjectTotem> get_totems(){
    	return totems;
    }
	public void add_totem(ClassObjectTotem totem){
		totems.add(totem);
	}
	public ArrayList<ClassObjectSpellDungeon> get_spells(){
    	return spells;
    }
	public void remove_spell(ClassObjectSpellDungeon spell){
		spells.remove(spell);
    }
	public ArrayList<ClassObjectPickupDungeon> get_pickups(){
		return pickups;
	}
	public void add_pickup(ClassObjectPickupDungeon pickup){
		pickups.add(pickup);
	}
	public void remove_pickup(ClassObjectPickupDungeon pickup){
		pickups.remove(pickup);
	}
	public ClassReferenceDrawable get_game_vars(){
		return game_vars;
	}
	public float get_shop_discount(){
		return shop_discount;
	}
	public void set_shop_discount(float shop_discount){
		this.shop_discount = shop_discount;
	}
}
